1include <BOSL2/std.scad>
2// Voronoi from https://github.com/felipesanches/OpenSCAD_Voronoi_Generator
3use <voronoi.scad>
4use <NotoSansMono-Bold.ttf>
5
6box_diameter = 86; //mm
7box_thickness = 28; //mm
8box_rounding = 10;//mm
9
10wall_thickness = 3;//mm
11
12register_thickness = 1; //mm
13register_depth = 1; //mm
14register_tolerance = 0.1;//mm
15register_friction_bars = 6;
16friction_bar_thickness=0.75;//mm
17friction_bar_length=1;//mm
18
19hinge_length = 60; //mm
20hinge_width = 30; //mm
21hinge_thickness = 0.6; //mm 3 0.2mm layers
22hinge_rounding = 15;//mm
23
24bottom_voronoi_seed = 100;
25top_voronoi_seed = 1541;
26voronoi_count = 100;
27voronoi_thickness=1;
28voronoi_rounding=0.5;
29voronoi_texture_thickness = 1.5; //mm
30voronoi_texture = false;
31
32text_texture_thickness = 1.5; //mm
33text_texture = true;
34
35binary_texture_thickness = 1.5; //mm
36binary_angle_pad = 0.0; // fraction
37binary_line_pad = 0.0; // fraction
38binary_width = 4;
39binary_offset = 2;
40binary_data = ["01111010"]; //["01010010", "01000001", "00110001", "00110111", "01101000", "00110100", "00110101", "01101101", "00110100", "00110000", "00101110", "00110000", "00110100", "00110000", "00111001", "01110011","01000100", "01100101", "01100011", "11100010", "10001000", "10010010", "00110010", "00111001", "11000010", "10110000", "00110000", "11100010", "10000000", "10110010", "00110010", "00111000", "00101110", "00110001", "00110001", "00111000", "11100010", "10000000", "10110011"];
41binary_read_start_indicator_radius = 1;
42binary_texture = true;
43
44textured_interior = true;
45interior_texture = "cubes"; // See https://github.com/revarbat/BOSL2/wiki/skin.scad#function-texture for available textures
46interior_texture_depth = 0.4; // multiplier
47interior_texture_size = [10,10];
48
49resolution = 200; // must be pair
50
51// code
52hinge_length_adjusted = box_diameter+hinge_length+hinge_width;
53
54module voronoi_polygon(border, n=30, thickness=1.7, round=1.0, edging=3.0, seed=undef) {
55
56 // bounding box
57 only_x = [ for (point = border) point[0] ];
58 only_y = [ for (point = border) point[1] ];
59 min_x = min(only_x);
60 min_y = min(only_y);
61 max_x = max(only_x);
62 max_y = max(only_y);
63 // echo([[min_x,min_y],[max_x,max_y]]);
64
65 // compute sizes, centers and scaling
66 size_x = max_x - min_x;
67 size_y = max_y - min_y;
68 L = max(size_x, size_y);
69 scale_voro = [ size_x / L, size_y / L ];
70 center_poly = [(min_x + max_x) / 2, (min_y + max_y) / 2];
71
72 // subtract Voronoi pattern from the border polygon (disabled)
73 difference() {
74 //polygon(border);
75 translate(center_poly) scale(scale_voro)
76 random_voronoi(n = n, nuclei = false, L = L, thickness = thickness,
77 round = round, min = 0, max = L, seed = seed, center = true);
78 }
79
80 // add the border edge if required
81 if (edging) {
82 difference() {
83 polygon(border);
84 offset(delta = -edging) polygon(border);
85 }
86 }
87}
88
89module register(bottom_part=true){
90applied_tolerance = bottom_part ? register_tolerance : -register_tolerance;
91 translate([0,0,box_thickness/4])
92tube(h=register_depth*2, od=box_diameter-wall_thickness+register_thickness+applied_tolerance, id=box_diameter-wall_thickness-register_thickness-applied_tolerance,$fn=
93resolution);
94for (i = [0 : 1 : register_friction_bars]) {
95angle_register_friction = 360*i/register_friction_bars;
96computed_bar_radius = box_diameter/2-wall_thickness/2;
97computed_bar_length = friction_bar_length+applied_tolerance/2;
98computed_bar_radius_min_length = computed_bar_radius-computed_bar_length;
99 translate([sin(angle_register_friction)*computed_bar_radius, cos(angle_register_friction)*computed_bar_radius, 0 ])
100 translate([0,0,box_thickness/4-register_depth]) rotate([0,0,-angle_register_friction]) cube([friction_bar_thickness+applied_tolerance/2,computed_bar_length,register_depth*2]);
101 translate([sin(angle_register_friction)*computed_bar_radius_min_length, cos(angle_register_friction)*computed_bar_radius_min_length, 0 ])
102 translate([0,0,box_thickness/4-register_depth]) rotate([0,0,-angle_register_friction]) cube([friction_bar_thickness+applied_tolerance/2,computed_bar_length,register_depth*2]);
103}
104}
105
106module box_half(bottom_part=true,voronoi_seed=1000){
107difference(){
108cyl(d=box_diameter, l=box_thickness/2, rounding1=box_rounding,$fn=
109resolution);
110if (textured_interior){
111translate([0,0,wall_thickness/2]) cyl(d=box_diameter-wall_thickness*2, l=box_thickness/2-wall_thickness, rounding1=box_rounding-wall_thickness, texture=interior_texture, tex_size=interior_texture_size,tex_scale=interior_texture_depth,$fn=
112resolution);
113} else {
114translate([0,0,wall_thickness/2]) cyl(d=box_diameter-wall_thickness*2, l=box_thickness/2-wall_thickness, rounding1=box_rounding-wall_thickness,$fn=
115resolution);
116}
117if (bottom_part){
118register(bottom_part);
119}
120potential_voronoi_texture(voronoi_seed);
121if (bottom_part){
122potential_texts();
123}
124if (!bottom_part){
125potential_binary();
126}
127}
128if (!bottom_part){
129register(bottom_part);
130}
131
132}
133
134external_texture_radius=box_diameter/2-box_rounding-wall_thickness;
135external_surface_offset =[0,0,-box_thickness/4];
136module potential_voronoi_texture(voronoi_seed=1000){
137if (voronoi_texture){
138border2 = [[box_diameter/2,box_diameter/2], [-box_diameter/2,box_diameter/2], [-box_diameter/2,-box_diameter/2], [box_diameter/2,-box_diameter/2]];
139translate(external_surface_offset)
140intersection(){
141linear_extrude(height = voronoi_texture_thickness) voronoi_polygon(border2,n=voronoi_count, thickness=voronoi_thickness, round=voronoi_rounding, edging=0, seed=voronoi_seed);
142 translate([0,0,wall_thickness/2])
143 cylinder(h=wall_thickness,r=external_texture_radius,center=true,$fn=
144resolution);
145 }
146 }
147}
148
149module revolve_text(radius, chars) {
150 PI = 3.14159;
151 circumference = 2 * PI * radius;
152 chars_len = len(chars);
153 font_size = circumference / chars_len;
154 step_angle = 360 / chars_len;
155 for(i = [0 : chars_len - 1]) {
156 rotate([0,180,i * step_angle])
157 translate([0, radius + font_size / 2, 0])
158 text(
159 chars[i],
160 font = "Noto Sans Mono:style=bold",
161 size = font_size,
162 valign = "center", halign = "center"
163 );
164 }
165}
166
167module potential_text(radius,text_string){
168translate(external_surface_offset)
169linear_extrude(height = text_texture_thickness) revolve_text(radius, text_string);
170}
171
172module potential_texts(){
173if (text_texture){
174potential_text(external_texture_radius-6,"Ad astra per aspera. ");
175 potential_text(external_texture_radius-8*2,"OnTake. 2023. ");
176 }
177 }
178
179 module sector(radius, angles, fn = 24) {
180 r = radius / cos(180 / fn);
181 step = -360 / fn;
182
183 points = concat([[0, 0]],
184 [for(a = [angles[0] : step : angles[1] - 360])
185 [r * cos(a), r * sin(a)]
186 ],
187 [[r * cos(angles[1]), r * sin(angles[1])]]
188 );
189
190 difference() {
191 circle(radius, $fn = fn);
192 polygon(points);
193 }
194}
195
196module arc(radius, angles, width = 1) {
197 difference() {
198 sector(radius + width, angles,fn=resolution/2);
199 sector(radius, angles,fn=resolution/2);
200 }
201}
202
203
204module binary_arcs(radius,binary,width){
205 translate([(radius+width+binary_read_start_indicator_radius),0,0]) circle(r=binary_read_start_indicator_radius,$fn=resolution);
206 line_count=len(binary);
207 for(line_index = [0 : line_count - 1]) {
208 bin_count = len(binary[line_index]);
209 angle_inc = 360/bin_count;
210 for(i = [0 : bin_count - 1]) {
211 if (binary[line_index][i] == "1"){
212 arc(radius-line_index*width+width*binary_line_pad, [i*angle_inc,(i+(1-binary_angle_pad))*angle_inc], width*(1-binary_line_pad));
213 }
214 }
215}
216}
217
218module potential_binary(){
219if (binary_texture){
220translate(external_surface_offset)
221linear_extrude(height = binary_texture_thickness) binary_arcs(external_texture_radius-binary_width-binary_offset,binary_data,binary_width);
222 }
223 }
224
225
226
227box_half(true,bottom_voronoi_seed);
228
229other_half_offset = [hinge_length_adjusted-hinge_width,0,0];
230
231translate(other_half_offset) box_half(false,top_voronoi_seed);
232
233difference(){
234
235translate([-hinge_width/2,-hinge_width/2,-box_thickness/4]) cuboid([hinge_length_adjusted,hinge_width,hinge_thickness],rounding=hinge_rounding,
236 edges=["Z"],anchor=BOTTOM+FRONT+LEFT);
237 potential_voronoi_texture(bottom_voronoi_seed);
238 translate(other_half_offset) potential_voronoi_texture(top_voronoi_seed);
239 potential_texts();
240 translate(other_half_offset) potential_binary();
241 }